class ReplicaSystem < ActiveRecord::Base
  has_and_belongs_to_many :programs
  has_many                :replicas

  validates_presence_of :name, :hostname
  
  before_save :sanitize_repository_path

  acts_as_authorizable
  
  PROTOCOLS = %w(Local FTP HTTP SMB).sort
  
  # Constants of supported protocols by Replica Systems
  Local = "Local"
  FTP   = "FTP"
  HTTP  = "HTTP"
  SMB   = "SMB"
  
  def self.find_remote_replication_systems
    self.find :all, :conditions => { :main => false }
  end
  
  # Returns the ReplicaSystem that is the Main Repository to the System
  def self.find_main_repository
    begin
      ReplicaSystem.find :first, :conditions => { :main => true }
  	rescue RecordNotFound
  	  nil
  	end
  end
  
  # Returns the path to store files in Main Repository
  def self.main_repository_path
    main = find_main_repository
    (main.hostname + main.internal_uri) unless main.nil?
  end 
  
  def find_replicated_assets    
    #assets
    AudioAsset.find_by_replica_system(self)
  end
  
  # Checks if Replication System has a replica from asset passed as argument.
  # A Replication System has a replica of an asset if:
  # - Exists in the system a replica that it's available
  # - Exists a replica associated to the system, not available, but exists a fetcher with a 'Replicate' operation
  def has_asset_replica?(asset)
    self.replicas.each { |replica| 
      if replica.audio_asset == asset && replica.file_type == AudioAsset::EssenceFileType
          return true if replica.available?
          replica.fetchers.each { |fetcher| return true if fetcher.action == Fetcher::Replicate }
      end
    }

    false
  end
  
  def require_authentication?
    !(self.username.nil? or self.username.blank?)
  end
  
  def main?
    self.main
  end
  
  #####################################
  # Access Control Methods
  #####################################
  def is_updatable_by(user)
    return false if user.blank?
    user.has_role? Role::Admin
  end
  
  def is_deletable_by(user)
    return false if user.blank?
	user.has_role? Role::Admin
  end
  
  def self.is_readable_by(user, object = nil)
    return false if user.blank?
	user.has_role? Role::Admin
  end
  
  def self.is_creatable_by(user)
    return false if user.blank?
    user.has_role? Role::Admin
  end
  ###################################


  private
  def sanitize_repository_path
    pattern_to_slashes = /((\\){1,}|\/)/
  	pattern_to_backslashes = /((\\){2,}|\/)/
    
  	case self.protocol
  	  when ReplicaSystem::Local
  	    # Replace Slashes and Backslashes by slashes
  	    self.hostname = self.hostname.gsub(pattern_to_slashes, '/')
  		self.internal_uri = self.internal_uri.gsub(pattern_to_slashes, '/') unless self.internal_uri.blank?
  
  	  when ReplicaSystem::SMB
  		# Remove two possible backslashes added by users, by mistake
  		self.hostname = self.hostname.gsub(/(\\){2,}/, '')
  		# Add two backslashes to the host of repository in LAN and replaces slashes by backslashes
  	    self.hostname = '\\\\' + self.hostname.gsub(pattern_to_backslashes, '\\')
  		self.internal_uri = self.internal_uri.gsub(pattern_to_backslashes, '\\') unless self.internal_uri.blank?
  		
  		# Make sure that the hostname and internal_uri ends with '\'
  		self.hostname = self.hostname + '\\' if (self.hostname =~ /.*[\\]/).nil?
  		self.internal_uri = self.internal_uri + '\\' if !self.internal_uri.blank? && (self.internal_uri =~ /.*[\\]/).nil?
  		
  	  when ReplicaSystem::FTP
  	    # Remove possible 'ftp:\\' added by user, by mistake
  		self.hostname = self.hostname.gsub(/(ftp:(\\\\)?)/, '')
  		# Add ftp:\\ to the FTP host and replaces slashes by backslashes
  		self.hostname = 'ftp:\\\\' + self.hostname.gsub(pattern_to_backslashes, '\\')
  		self.internal_uri = self.internal_uri.gsub(pattern_to_backslashes, '\\') unless self.internal_uri.blank?
  		
  		# Make sure that the hostname and internal_uri ends with '\'
  		self.hostname = self.hostname + '\\' if (self.hostname =~ /.*[\\]/).nil?
  		self.internal_uri = self.internal_uri + '\\' if !self.internal_uri.blank? && (self.internal_uri =~ /.*[\\]/).nil?
  		
  	  when ReplicaSystem::HTTP
  	    # Remove possible 'http:\\' or 'http://' added by user, by mistake
  		self.hostname = self.hostname.gsub(/(http:?((\/\/)|(\\\\))?)/, '')
  		# Add http:// to the HTTP host and replaces slashes by backslashes
  		self.hostname = 'http://' + self.hostname
  		self.internal_uri = self.internal_uri.gsub(pattern_to_slashes, '/') unless self.internal_uri.blank?
  		
  		# Make sure that the hostname and internal_uri ends with '/'
  		self.hostname = self.hostname + '/' if (self.hostname =~ /.*[\/]/).nil?
  		self.internal_uri = self.internal_uri + '/' if !self.internal_uri.blank? && (self.internal_uri =~ /.*[\/]/).nil?
  	end
  end
end
